#pragma once
#include <map>
#include <vector>
class Node;
class Edge {
public:
	const static int NULL_TYPE;
	Node* start;
	Node* end;
	int type;
	Edge(int t, Node* s, Node* e);
};



class Node {
public:
	const static int NULL_TYPE;
	const static int START_TYPE;
	const static int END_TYPE;
	const static int NORMAL_TYPE;
	std::map<int, std::vector<Edge>> adjs;
	std::vector<Edge> in;
	int type;
	Node(int t);
	virtual void addEdge(int t, Node* dst);
	virtual std::vector<Edge> getEdgeOf(int t);
	virtual std::vector<Edge> getAdjEdges();
	virtual void removeEdge(const Edge& e);
	virtual void changeTo(const Edge& edge, Node* newNode);
};

class RangeNode : public Node {
public:
	const static int RANGE_TYPE;
	RangeNode(int t, int s, int e, Node* endNode);
	explicit RangeNode(Node* endNode);
	void changeTo(const Edge& edge, Node* newNode) override;
	std::vector<Edge> getEdgeOf(int t) override;
	void addRange(int s, int e);
private:
	std::vector<int> start, end;
	Node* endNode;
};

class NFA {
public:
	Node* start;
	Node* end;
	NFA();
	NFA(Node* s, Node* e);
	bool isValid();
};